package org.abettor.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 类成员反射工具
 * @author <a href="http://www.abettor.org/" target="_blank">abettor</a>
 */
public class ReflectHelper
{
	private Object instance = null;

	/**
	 * 构造函数<br />
	 * 当针对某个具体实例操作的时候，可以用此方法构造一个对象
	 * @param instance 实例对象
	 */
	public ReflectHelper(Object instance)
	{
		this.instance = instance;
	}

	/**
	 * 获取对象的构造函数
	 * @param paramClasses 参数类列表
	 * @return 构造函数对象
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 */
	public Constructor<?> getConstructor(Class<?>[] paramClasses)
	throws NoSuchMethodException
	{
		if(instance == null)
		{
			return null;
		}

		Class<?> clazz = instance.getClass();
		return clazz.getConstructor(paramClasses);
	}

	/**
	 * 获取一个与指定对象相同类型的实例
	 * @param paramClasses 参数类列表
	 * @param params 参数对象列表
	 * @return 实例对象
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public Object newInstance(Class<?>[] paramClasses, Object[] params)
	throws NoSuchMethodException, IllegalArgumentException,
	InstantiationException, IllegalAccessException, InvocationTargetException
	{
		Constructor<?> constructor = this.getConstructor(paramClasses);
		return constructor.newInstance(params);
	}

	/**
	 * 获取指定类的构造函数
	 * @param clazz 指定类对象
	 * @param paramClasses 参数类列表
	 * @return 构造函数对象
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 */
	public static Constructor<?> getConstructor(Class<?> clazz, Class<?>[] paramClasses)
	throws NoSuchMethodException
	{
		return clazz.getConstructor(paramClasses);
	}

	/**
	 * 获取一个与指定对象相同类型的实例
	 * @param clazz 指定类对象
	 * @param paramClasses 参数类列表
	 * @param params 参数对象列表
	 * @return 实例对象
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public static Object newInstance(Class<?> clazz, Class<?>[] paramClasses, Object[] params)
	throws NoSuchMethodException, IllegalArgumentException,
	InstantiationException, IllegalAccessException, InvocationTargetException
	{
		Constructor<?> constructor = ReflectHelper.getConstructor(clazz, paramClasses);
		return constructor.newInstance(params);
	}

	/**
	 * 获取指定类的构造函数
	 * @param className 指定类的长名称
	 * @param paramClassNames 构造函数的参数类长名称列表
	 * @return 构造函数对象
	 * @throws ClassNotFoundException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 */
	public static Constructor<?> getConstructor(String className, String[] paramClassNames)
	throws ClassNotFoundException, SecurityException, NoSuchMethodException
	{
		Class<?> clazz = Class.forName(className);
		int len = paramClassNames.length;
		Class<?>[] paramClasses = new Class[len];
		for(int i = 0; i < len; i ++)
		{
			paramClasses[i] = Class.forName(paramClassNames[i]);
		}

		return clazz.getConstructor(paramClasses);
	}

	/**
	 * 获取一个与指定对象相同类型的实例
	 * @param className 指定类的长名称
	 * @param paramClassNames 构造函数的参数类长名称列表
	 * @param params 参数对象列表
	 * @return 构造函数对象
	 * @throws SecurityException
	 * @throws ClassNotFoundException
	 * @throws NoSuchMethodException
	 * @throws IllegalArgumentException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public static Object newInstance(String className, String[] paramClassNames, Object params)
	throws SecurityException, ClassNotFoundException,
	NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException
	{
		Constructor<?> constructor = ReflectHelper.getConstructor(className, paramClassNames);
		return constructor.newInstance(params);
	}

	/**
	 * 获取对象中的指定属性对象
	 * @param propertyName 属性名称
	 * @return 属性对象
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	public Field getProperty(String propertyName)
	throws SecurityException, NoSuchFieldException
	{
		if(instance == null)
		{
			return null;
		}

		Class<?> clazz = instance.getClass();
		return clazz.getField(propertyName);
	}

	/**
	 * 获取对象中的指定属性对象的值
	 * @param propertyName 属性名称
	 * @return 属性对象的值
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	public Object getPropertyValue(String propertyName)
	throws IllegalArgumentException, IllegalAccessException,
	SecurityException, NoSuchFieldException
	{
		Field prop = this.getProperty(propertyName);
		return prop.get(instance);
	}

	/**
	 * 设置对象中的指定属性对象的值
	 * @param propertyName 属性名称
	 * @param value 属性对象的新值
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	public void setPropertyValue(String propertyName, Object value)
	throws IllegalArgumentException, IllegalAccessException,
	SecurityException, NoSuchFieldException
	{
		Field prop = this.getProperty(propertyName);
		prop.set(instance, value);
	}

	/**
	 * 获取指定类中的指定属性对象
	 * @param clazz 类对象
	 * @param propertyName 属性名称
	 * @return 属性对象
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	public static Field getProperty(Class<?> clazz, String propertyName)
	throws SecurityException, NoSuchFieldException
	{
		return clazz.getField(propertyName);
	}

	/**
	 * 获取指定对象中的指定属性对象的值
	 * @param clazz 类对象
	 * @param instance 类实例对象<br />如果属性为静态属性，则类实例可以为null
	 * @param propertyName 属性名称
	 * @return 属性对象的值
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	public static Object getPropertyValue(Class<?> clazz, Object instance, String propertyName)
	throws IllegalArgumentException, IllegalAccessException,
	SecurityException, NoSuchFieldException
	{
		Field prop = ReflectHelper.getProperty(clazz, propertyName);
		return prop.get(instance);
	}

	/**
	 * 设置指定对象中的指定属性对象的值
	 * @param clazz 类对象
	 * @param instance 类实例对象<br />如果属性为静态属性，则类实例可以为null
	 * @param propertyName 属性名称
	 * @param value 属性的新值
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 */
	public static void setPropertyValue(Class<?> clazz, Object instance, String propertyName, Object value)
	throws IllegalArgumentException, IllegalAccessException,
	SecurityException, NoSuchFieldException
	{
		Field prop = ReflectHelper.getProperty(clazz, propertyName);
		prop.set(instance, value);
	}

	/**
	 * 获取类名称所指定的类中的属性对象
	 * @param className 类的长名称
	 * @param propertyName 属性名称
	 * @return 属性对象
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 * @throws ClassNotFoundException
	 */
	public static Field getProperty(String className, String propertyName)
	throws SecurityException, NoSuchFieldException, ClassNotFoundException
	{
		Class<?> clazz = Class.forName(className);
		return clazz.getField(propertyName);
	}

	/**
	 * 获取类名称所指定的类中的属性对象的值
	 * @param className 类的长名称
	 * @param instance 类实例对象<br />如果属性为静态属性，则类实例可以为null
	 * @param propertyName 属性名称
	 * @return 属性对象的值
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 * @throws ClassNotFoundException
	 */
	public static Object getPropertyValue(String className, Object instance, String propertyName)
	throws IllegalArgumentException, IllegalAccessException,
	SecurityException, NoSuchFieldException, ClassNotFoundException
	{
		Field prop = ReflectHelper.getProperty(className, propertyName);
		return prop.get(instance);
	}

	/**
	 * 设置类名称所指定的类中的属性对象的值
	 * @param className 类的长名称
	 * @param instance 类实例对象<br />如果属性为静态属性，则类实例可以为null
	 * @param propertyName 属性名称
	 * @param value 属性的新值
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws SecurityException
	 * @throws NoSuchFieldException
	 * @throws ClassNotFoundException
	 */
	public static void setPropertyValue(String className, Object instance, String propertyName, Object value)
	throws IllegalArgumentException, IllegalAccessException,
	SecurityException, NoSuchFieldException, ClassNotFoundException
	{
		Field prop = ReflectHelper.getProperty(className, propertyName);
		prop.set(instance, value);
	}

	/**
	 * 获取对象中指定的方法对象
	 * @param methodName 方法名
	 * @param paramClasses 参数类列表
	 * @return 方法对象
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 */
	public Method getMethod(String methodName, Class<?>[] paramClasses)
	throws SecurityException, NoSuchMethodException
	{
		if(instance == null)
		{
			return null;
		}

		Class<?> clazz = instance.getClass();
		return clazz.getMethod(methodName, paramClasses);
	}

	/**
	 * 调用对象中的某个方法
	 * @param methodName 方法名
	 * @param paramClasses 参数类列表
	 * @param params 参数类表
	 * @return 被调用方法的返回值<br />如果所调用的方法无返回值，则返回null
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 */
	public Object invokeMethod(String methodName, Class<?>[] paramClasses, Object[] params)
	throws IllegalArgumentException, IllegalAccessException,
	InvocationTargetException, SecurityException, NoSuchMethodException
	{
		Method method = this.getMethod(methodName, paramClasses);
		return method.invoke(instance, params);
	}

	/**
	 * 获取指定类对象中的指定的方法对象
	 * @param clazz 指定类对象
	 * @param methodName 方法名
	 * @param paramClasses 参数类表
	 * @return 方法对象
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 */
	public static Method getMethod(Class<?> clazz, String methodName, Class<?>[] paramClasses)
	throws SecurityException, NoSuchMethodException
	{
		return clazz.getMethod(methodName, paramClasses);
	}

	/**
	 * 调用指定类对象中的指定的方法
	 * @param clazz 指定类对象
	 * @param instance 指定类的实例
	 * @param methodName 方法明
	 * @param paramClasses 参数类列表
	 * @param params 参数列表
	 * @return 被调用方法的返回值<br />如果所调用的方法无返回值，则返回null
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 */
	public static Object invokeMethod(Class<?> clazz, Object instance, String methodName, Class<?>[] paramClasses, Object[] params)
	throws IllegalArgumentException, IllegalAccessException,
	InvocationTargetException, SecurityException, NoSuchMethodException
	{
		Method method = ReflectHelper.getMethod(clazz, methodName, paramClasses);
		return method.invoke(instance, params);
	}

	/**
	 * 获取类名称所指定的类中的指定的方法对象
	 * @param className 类对象的长名称
	 * @param methodName 方法名
	 * @param paramClassNames 参数类长名称类表
	 * @return 方法对象
	 * @throws ClassNotFoundException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 */
	public static Method getMethod(String className, String methodName, String[] paramClassNames)
	throws ClassNotFoundException, SecurityException, NoSuchMethodException
	{
		Class<?> clazz = Class.forName(className);
		int paramLen = paramClassNames.length;
		Class<?>[] params = new Class[paramLen];
		for(int i = 0; i < paramLen; i ++)
		{
			params[i] = Class.forName(paramClassNames[i]);
		}
		return clazz.getMethod(methodName, params);
	}

	/**
	 * 调用类名称所指定的类中的指定的方法
	 * @param className 指定类的长名称
	 * @param instance 指定类的实例
	 * @param methodName 方法名
	 * @param paramClasses 参数类长名称类表
	 * @param params 参数列表
	 * @return 被调用方法的返回值<br />如果所调用的方法无返回值，则返回null
	 * @throws IllegalArgumentException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * @throws ClassNotFoundException
	 * @throws SecurityException
	 * @throws NoSuchMethodException
	 */
	public static Object invokeMethod(String className, Object instance, String methodName, Class<?>[] paramClasses, Object[] params)
	throws IllegalArgumentException, IllegalAccessException,
	InvocationTargetException, ClassNotFoundException,
	SecurityException, NoSuchMethodException
	{
		Class<?> clazz = Class.forName(className);
		Method method = ReflectHelper.getMethod(clazz, methodName, paramClasses);
		return method.invoke(instance, params);
	}
}
